package com.dianziq.im.server;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * 
 * @author wxj
 * 
 */
public class DBBag {
	private static final Logger log=Logger.getLogger(DBBag.class);
	Connection con = createConnection();
	static private ThreadLocal<DBBag> dbBags = new ThreadLocal() {
		protected DBBag initialValue() {
			return new DBBag();
		}
	};
	static private String driverName = "org.gjt.mm.mysql.Driver";
	static private String dbURL = Config.INSTANCE.get("mysql-jdbc-url");
	static private String userName = Config.INSTANCE.get("dbuser");
	static private String userPwd = Config.INSTANCE.get("dbpwd");

	static private Connection createConnection() {
		try {
			Class.forName(driverName);
			return DriverManager.getConnection(dbURL, userName, userPwd);
		} catch (Exception e) {
			log.debug("数据库连接不能打开",e);
			return null;
		}

	}

	public static Connection getConnection() throws SQLException {
		
		Connection c=dbBags.get().con;
		if(c.isClosed())
		{
			c= createConnection() ;
			dbBags.get().con=c;
			
		}
		return c;
	}

	@Override
	protected void finalize() throws Throwable {
		try {
			con.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
		super.finalize();
	}
	public static interface Mapper<T> {
		public T map(java.sql.ResultSet res)  throws SQLException;
	}
	public static interface StatementExecuter {
		public void doInStatement(Statement stat) throws SQLException;
	}

	public static void executeSql(final String sql) throws SQLException {
		executeStatement(new StatementExecuter() {
			public void doInStatement(Statement stat) throws SQLException {
				try {
					stat.execute(sql);
				} catch (SQLException e) {
				log.debug("ErrorSQL:{}"+sql,e);
					throw e;
				}
			}
		});
	}

	public static void executeSql(Connection c, final String sql)
			throws SQLException {
		executeSql(c, sql, false);
	}

	public static void executeSql(Connection c, final String sql, boolean close)
			throws SQLException {
		// log.trace("SQL:{}", sql);
		executeStatement(c, new StatementExecuter() {
			public void doInStatement(Statement stat) throws SQLException {
				try {
					stat.execute(sql);
				} catch (SQLException e) {
					log.debug("ErrorSQL:{}"+sql,e);
					throw e;
				}
			}
		}, close);
	}

	public static interface ResultSetHandler {
		public void handlerResultSet(java.sql.ResultSet res)
				throws SQLException;
	}

	public static void doResultSet(Connection c, final String sql,
			final ResultSetHandler rsh) throws SQLException {
		doResultSet(c, sql, rsh, false);
	}

	public static void doResultSet(Connection c, final String sql,
			final ResultSetHandler rsh, boolean close) throws SQLException {
		executeStatement(c, new StatementExecuter() {
			public void doInStatement(Statement stat) throws SQLException {
				java.sql.ResultSet res = stat.executeQuery(sql);
				try {
					rsh.handlerResultSet(res);
				} finally {
					res.close();
				}
			}
		}, close);
	}

	

	public static <T> List<T> getList(final String sql, final Mapper<T> mapper)
			throws SQLException {

		final List<T> l = new ArrayList<T>();
		executeStatement(new StatementExecuter() {
			public void doInStatement(Statement stat) throws SQLException {
				java.sql.ResultSet res = stat.executeQuery(sql);
				try {
					while (res.next()) {
						l.add(mapper.map(res));
						
					}
				} finally {
					res.close();
				}
			}
		});
		return l;

	}

	public static void doResultSet(final String sql, final ResultSetHandler rsh)
			throws SQLException {
		executeStatement(new StatementExecuter() {
			public void doInStatement(Statement stat) throws SQLException {
				java.sql.ResultSet res = stat.executeQuery(sql);
				try {
					rsh.handlerResultSet(res);
				} finally {
					res.close();
				}
			}
		});

	}

	// private static Connection pooledConnection;
	public static void executeStatement(Connection c, StatementExecuter se)
			throws SQLException {
		executeStatement(c, se, false);
	}

	public static void executeStatement(Connection c, StatementExecuter se,
			boolean close) throws SQLException {
		boolean ok = false;
		try {
			Statement stat = c.createStatement();
			try {
				se.doInStatement(stat);
				ok = true;
			} finally {
				stat.close();
			}
		} finally {
			if (!c.isClosed() && (close || !ok)) {
				c.close();
			}
		}
	}

	public static void executeStatement(StatementExecuter se)
			throws SQLException {

		executeStatement(getConnection(), se);

	}
	 

}